home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
dev
/
cross
/
GBDK-2.0.lha
/
GBDK
/
lib
/
rand.s
< prev
next >
Wrap
Text File
|
1998-10-01
|
4KB
|
118 lines
;/***************************************************************************
; * *
; * Module : rand.s *
; * *
; * Purpose : A rand() generator using the linear congruential method *
; * *
; * Version : 1.01, January 7 1998 *
; * Added _initrand to set seed without recompiling *
; * 1, January 6 1998 *
; * *
; * Author : Luc Van den Borre ( Homepage : NOC.BASE.ORG ) *
; * *
; **************************************************************************/
;; Why use an algorithm for generating random numbers?
;;
;; - Given a certain seed value, the same sequence of random numbers is generated
;; every time. This is a good thing when debugging (reproducible). On the other
;; hand, you've got 2^16 seed values, each of which will produce a sequence of
;; numbers that stays different for any of the other sequences for 'an appreciable
;; time.' (I can't say how long exactly.)
;;
;; - The linear congruential method is one of the 'best' random number generators
;; around. However, this implementation uses a 16 bit accumulator, while at least
;; 32 bits are needed for a generator that passes all the statistical tests.
;; Still, I'm relatively confident that this is random enough for even the most
;; demanding game.
;;
;; Compare this to getting random values from one of the hardware registers
;; (not reproducible, might not have all values). An array might be the best bet
;; if you don't need a lot of values (or have lots of memory spare),
;; or if you want values to be within a certain range.
;; And both would be faster than this. Also, this definitely isn't the fastest
;; algorithm I know, and certainly for games less strict algorithms might be
;; appropriate (shift and xor ?).
;; It's your choice - but if you're doing Monte Carlo physics simulations on the
;; GameBoy, this is a safe bet!
.include "global.s"
.area _BSS
.randhi:: ; Storage for last random number (or seed)
.ds 0x01
.randlo::
.ds 0x01
.area _CODE
;; Random number generator using the linear congruential method
;; X(n+1) = (a*X(n)+c) mod m
;; with a = 17, m = 16 and c = $5c93 (arbitrarily)
;; The seed value is also chosen arbitrarily as $a27e
;; Ref : D. E. Knuth, "The Art of Computer Programming" , Volume 2
;;
;; Exit conditions
;; DE = Random number [0,2^16-1]
;;
;; Registers used:
;; A, HL (need not be saved) and DE (return register)
;;
_rand::
_randw::
LD A, (.randlo)
LD L, A
LD E, A ; Save randlo
LD A, (.randhi)
LD D, A ; Save randhi
SLA L ; * 16
RLA
SLA L
RLA
SLA L
RLA
SLA L
RLA
LD H, A ; Save randhi*16
LD A, E ; Old randlo
ADD A, L ; Add randlo*16
LD L, A ; Save randlo*17
LD A, H ; randhi*16
ADC A, D ; Add old randhi
LD H, A ; Save randhi*17
LD A, L ; randlo*17
ADD A, #0x93
LD (.randlo), A
LD D, A ; Return register
LD A, H ; randhi*17
ADC A, #0x5c
LD (.randhi), A
LD E, A ; Return register
;; Note D is the low byte, E the high byte. This is intentional because
;; the high byte can be slightly 'more random' than the low byte, and I presume
;; most will cast the return value to a UBYTE. As if someone will use this, tha!
RET
;; This sets the seed value. Call it whenever you like
;;
;; Exit conditions
;; None
;;
;; Registers used:
;; A, HL (need not be saved) and DE (return register)
;;
_initrand::
LDA HL,2(SP)
.initrand::
LD A, (HL+)
LD (.randlo), A
LD A, (HL)
LD (.randhi), A
RET